home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint108s.zoo / biosfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-27  |  33.7 KB  |  1,507 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1993 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* simple biosfs.c */
  8.  
  9. #include "mint.h"
  10.  
  11. extern struct kerinfo kernelinfo;    /* see main.c */
  12.  
  13. static long    ARGS_ON_STACK bios_root    P_((int drv, fcookie *fc));
  14. static long    ARGS_ON_STACK bios_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  15. static long    ARGS_ON_STACK bios_getxattr    P_((fcookie *fc, XATTR *xattr));
  16. static long    ARGS_ON_STACK bios_chattr    P_((fcookie *fc, int attrib));
  17. static long    ARGS_ON_STACK bios_chown    P_((fcookie *fc, int uid, int gid));
  18. static long    ARGS_ON_STACK bios_chmode    P_((fcookie *fc, unsigned mode));
  19. static long    ARGS_ON_STACK bios_rmdir    P_((fcookie *dir, const char *name));
  20. static long    ARGS_ON_STACK bios_remove    P_((fcookie *dir, const char *name));
  21. static long    ARGS_ON_STACK bios_getname    P_((fcookie *root, fcookie *dir, char *pathname, int size));
  22. static long    ARGS_ON_STACK bios_rename    P_((fcookie *olddir, char *oldname,
  23.                     fcookie *newdir, const char *newname));
  24. static long    ARGS_ON_STACK bios_opendir    P_((DIR *dirh, int flags));
  25. static long    ARGS_ON_STACK bios_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *fc));
  26. static long    ARGS_ON_STACK bios_rewinddir    P_((DIR *dirh));
  27. static long    ARGS_ON_STACK bios_closedir    P_((DIR *dirh));
  28. static long    ARGS_ON_STACK bios_pathconf    P_((fcookie *dir, int which));
  29. static long    ARGS_ON_STACK bios_dfree    P_((fcookie *dir, long *buf));
  30. static DEVDRV *    ARGS_ON_STACK bios_getdev    P_((fcookie *fc, long *devspecial));
  31. static long    ARGS_ON_STACK bios_fscntl    P_((fcookie *, const char *, int, long));
  32. static long    ARGS_ON_STACK bios_symlink    P_((fcookie *, const char *, const char *));
  33. static long    ARGS_ON_STACK bios_readlink    P_((fcookie *, char *, int));
  34.  
  35. static long    ARGS_ON_STACK bios_topen    P_((FILEPTR *f));
  36. static long    ARGS_ON_STACK bios_twrite    P_((FILEPTR *f, const char *buf, long bytes));
  37. static long    ARGS_ON_STACK bios_tread    P_((FILEPTR *f, char *buf, long bytes));
  38. static long    ARGS_ON_STACK bios_nwrite    P_((FILEPTR *f, const char *buf, long bytes));
  39. static long    ARGS_ON_STACK bios_nread    P_((FILEPTR *f, char *buf, long bytes));
  40. static long    ARGS_ON_STACK bios_ioctl    P_((FILEPTR *f, int mode, void *buf));
  41. static long    ARGS_ON_STACK bios_select    P_((FILEPTR *f, long p, int mode));
  42. static void    ARGS_ON_STACK bios_unselect    P_((FILEPTR *f, long p, int mode));
  43. static long    ARGS_ON_STACK bios_tseek    P_((FILEPTR *f, long where, int whence));
  44.  
  45. long    ARGS_ON_STACK null_open    P_((FILEPTR *f));
  46. long    ARGS_ON_STACK null_write    P_((FILEPTR *f, const char *buf, long bytes));
  47. long    ARGS_ON_STACK null_read    P_((FILEPTR *f, char *buf, long bytes));
  48. long    ARGS_ON_STACK null_lseek    P_((FILEPTR *f, long where, int whence));
  49. long    ARGS_ON_STACK null_ioctl    P_((FILEPTR *f, int mode, void *buf));
  50. long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  51. long    ARGS_ON_STACK null_close    P_((FILEPTR *f, int pid));
  52. long    ARGS_ON_STACK null_select    P_((FILEPTR *f, long p, int mode));
  53. void    ARGS_ON_STACK null_unselect    P_((FILEPTR *f, long p, int mode));
  54.  
  55. static long ARGS_ON_STACK mouse_open    P_((FILEPTR *f));
  56. static long ARGS_ON_STACK mouse_read    P_((FILEPTR *f, char *buf, long nbytes));
  57. static long ARGS_ON_STACK mouse_ioctl P_((FILEPTR *f, int mode, void *buf));
  58. static long ARGS_ON_STACK mouse_close P_((FILEPTR *f, int pid));
  59. static long ARGS_ON_STACK mouse_select P_((FILEPTR *f, long p, int mode));
  60. static void ARGS_ON_STACK mouse_unselect P_((FILEPTR *f, long p, int mode));
  61.  
  62. /* device driver for BIOS terminals */
  63.  
  64. DEVDRV bios_tdevice = {
  65.     bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl,
  66.     null_datime, null_close, bios_select, bios_unselect
  67. };
  68.  
  69. /* device driver for BIOS devices that are not terminals */
  70.  
  71. DEVDRV bios_ndevice = {
  72.     null_open, bios_nwrite, bios_nread, null_lseek, bios_ioctl,
  73.     null_datime, null_close, bios_select, bios_unselect
  74. };
  75.  
  76. DEVDRV null_device = {
  77.     null_open, null_write, null_read, null_lseek, null_ioctl,
  78.     null_datime, null_close, null_select, null_unselect
  79. };
  80.  
  81. DEVDRV mouse_device = {
  82.     mouse_open, null_write, mouse_read, null_lseek, mouse_ioctl,
  83.     null_datime, mouse_close, mouse_select, mouse_unselect
  84. };
  85.  
  86. /* this special driver is checked for in dosfile.c, and indicates that
  87.  * a dup operation is actually wanted rather than an open
  88.  */
  89. DEVDRV fakedev;
  90.  
  91. #ifdef FASTTEXT
  92. extern DEVDRV screen_device;    /* see fasttext.c */
  93. #endif
  94.  
  95. FILESYS bios_filesys = {
  96.     (FILESYS *)0,
  97.     FS_LONGPATH,
  98.     bios_root,
  99.     bios_lookup, nocreat, bios_getdev, bios_getxattr,
  100.     bios_chattr, bios_chown, bios_chmode,
  101.     nomkdir, bios_rmdir, bios_remove, bios_getname, bios_rename,
  102.     bios_opendir, bios_readdir, bios_rewinddir, bios_closedir,
  103.     bios_pathconf, bios_dfree, nowritelabel, noreadlabel,
  104.     bios_symlink, bios_readlink, nohardlink, bios_fscntl, nodskchng
  105. };
  106.  
  107.  
  108. struct tty con_tty, aux_tty, midi_tty;
  109. struct tty sccb_tty, scca_tty, ttmfp_tty;
  110.  
  111. #define BNAME_MAX    13
  112.  
  113. struct bios_file {
  114.     char     name[BNAME_MAX+1];    /* device name */
  115.     DEVDRV *device;            /* device driver for device */
  116.     short    private;        /* extra info for device driver */
  117.     ushort    flags;            /* flags for device open */
  118.     struct tty *tty;        /* tty structure (if appropriate) */
  119.     struct bios_file *next;
  120. };
  121.  
  122. struct bios_file BDEV[] = {
  123.  
  124. /* "real" bios devices present on all machines */
  125.     {"centr", &bios_ndevice, 0, 0, 0, 0},
  126.     {"console", &bios_tdevice, 2, O_TTY, &con_tty, 0},
  127.     {"midi", &bios_tdevice, 3, O_TTY, &midi_tty, 0},
  128.     {"kbd", &bios_ndevice, 4, 0, 0, 0},
  129. /* devices that duplicate handles */
  130.     {"prn", &fakedev, -3, 0, 0, 0}, /* handle -3 (printer) */
  131.     {"aux", &fakedev, -2, 0, 0, 0}, /* handle -2 (aux. terminal) */
  132.     {"con", &fakedev, -1, 0, 0, 0}, /* handle -1 (control terminal) */
  133.     {"tty", &fakedev, -1, 0, 0, 0}, /* the Unix name for it */
  134.     {"stdin", &fakedev, 0, 0, 0, 0},  /* handle 0 (stdin) */
  135.     {"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */
  136.     {"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */
  137.  
  138. /* other miscellaneous devices */
  139.     {"mouse", &mouse_device, 0, 0, 0, 0},
  140.     {"null", &null_device, 0, 0, 0, 0},
  141.  
  142. #ifdef FASTTEXT
  143. /* alternate console driver */
  144.     {"fasttext", &screen_device, 2, O_TTY, &con_tty, 0},
  145. #endif
  146.  
  147. /* serial port things *must* come last, because not all of these
  148.  * are present on all machines (except for modem1, which does however
  149.  * have a different device number on TTs and STs)
  150.  */
  151.     {"modem1", &bios_tdevice, 6, O_TTY, &aux_tty, 0},
  152.     {"modem2", &bios_tdevice, 7, O_TTY, &sccb_tty, 0},
  153.     {"serial1", &bios_tdevice, 8, O_TTY, &ttmfp_tty, 0},
  154.     {"serial2", &bios_tdevice, 9, O_TTY, &scca_tty, 0},
  155.     {"", 0, 0, 0, 0, 0}
  156. };
  157.  
  158. struct bios_file *broot, *bdevlast;
  159.  
  160. /* a file pointer for BIOS device 1, provided only for insurance
  161.  * in case a Bconmap happens and we can't allocate a new FILEPTR;
  162.  * in most cases, we'll want to build a FILEPTR in the usual
  163.  * way.
  164.  */
  165.  
  166. FILEPTR *defaultaux;
  167.  
  168. void
  169. biosfs_init()
  170. {
  171.     struct bios_file *b;
  172.  
  173.     broot = BDEV;
  174.  
  175.     for (b = broot; b->name[0]; b++) {
  176.         b->next = b+1;
  177.  
  178.     /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
  179.      * device 1
  180.      * and ignore the remaining devices, since they're not present
  181.      */
  182.         if (!has_bconmap && b->private == 6) {
  183.             b->private = 1;
  184.             b->next = 0;
  185.             break;
  186.         }
  187.     /* SERIAL2 is not present on the Mega STe */
  188.         if (mch == MEGASTE && b->private == 8) {
  189.             b->next = 0;
  190.             break;
  191.         }
  192.             
  193.     }
  194.     bdevlast = b;
  195.     if (b->name[0] == 0) {
  196.         --b;
  197.         b->next = 0;
  198.     }
  199.     defaultaux = new_fileptr();
  200.     defaultaux->links = 1;        /* so it never gets freed */
  201.     defaultaux->flags = O_RDWR;
  202.     defaultaux->pos = 0;
  203.     defaultaux->devinfo = 0;
  204.     defaultaux->fc.fs = &bios_filesys;
  205.     defaultaux->fc.index = 0;
  206.     defaultaux->fc.aux = 1;
  207.     defaultaux->fc.dev = BIOSDRV;
  208.     defaultaux->dev = &bios_ndevice;
  209. }
  210.  
  211. static long ARGS_ON_STACK 
  212. bios_root(drv, fc)
  213.     int drv;
  214.     fcookie *fc;
  215. {
  216.     if (drv == BIOSDRV) {
  217.         fc->fs = &bios_filesys;
  218.         fc->dev = drv;
  219.         fc->index = 0L;
  220.         return 0;
  221.     }
  222.     fc->fs = 0;
  223.     return EINTRN;
  224. }
  225.  
  226. static long ARGS_ON_STACK 
  227. bios_lookup(dir, name, fc)
  228.     fcookie *dir;
  229.     const char *name;
  230.     fcookie *fc;
  231. {
  232.     struct bios_file *b;
  233.  
  234.     if (dir->index != 0) {
  235.         DEBUG(("bios_lookup: bad directory"));
  236.         return EPTHNF;
  237.     }
  238. /* special case: an empty name in a directory means that directory */
  239. /* so does "." */
  240.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  241.         *fc = *dir;
  242.         return 0;
  243.     }
  244.  
  245. /* another special case: ".." could be a mount point */
  246.     if (!strcmp(name, "..")) {
  247.         *fc = *dir;
  248.         return EMOUNT;
  249.     }
  250.  
  251.     for (b = broot; b; b = b->next) {
  252.         if (!stricmp(b->name, name)) {
  253.             fc->fs = &bios_filesys;
  254.             fc->index = (long)b;
  255.             fc->aux = b->private;
  256.             fc->dev = dir->dev;
  257.             return 0;
  258.         }
  259.     }
  260.     DEBUG(("bios_lookup: name(%s) not found", name));
  261.     return EFILNF;
  262. }
  263.  
  264. static long ARGS_ON_STACK 
  265. bios_getxattr(fc, xattr)
  266.     fcookie *fc;
  267.     XATTR *xattr;
  268. {
  269.     FILEPTR *f;
  270.     struct bios_file *b = (struct bios_file *)fc->index;
  271.  
  272.     xattr->index = fc->index;
  273.     xattr->dev = fc->dev;
  274.     xattr->nlink = 1;
  275.     xattr->uid = xattr->gid = 0;
  276.     xattr->size = xattr->nblocks = 0;
  277.     xattr->blksize = 1;
  278.     xattr->mtime = xattr->atime = xattr->ctime = timestamp;
  279.     xattr->mdate = xattr->adate = xattr->cdate = datestamp;
  280.     if (fc->index == 0) {        /* root directory? */
  281.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  282.         xattr->attr = FA_DIR;
  283.     } else if (b->device == 0) {    /* symbolic link? */
  284.         xattr->mode = S_IFLNK | DEFAULT_DIRMODE;
  285.     } else if (b->device == &fakedev &&
  286.         (f = curproc->handle[b->private]) != 0)
  287.     {
  288.         /* u:\dev\stdin, u:\dev\stdout, etc. */
  289.         (*f->fc.fs->getxattr) (&f->fc, xattr);
  290.         xattr->index = fc->index;
  291.         xattr->dev = fc->dev;
  292.     } else {
  293.         xattr->mode = S_IFCHR | DEFAULT_MODE;
  294.         xattr->attr = 0;
  295.     }
  296.     return 0;
  297. }
  298.  
  299. static long ARGS_ON_STACK 
  300. bios_chattr(fc, attrib)
  301.     fcookie *fc;
  302.     int attrib;
  303. {
  304.     UNUSED(fc); UNUSED(attrib);
  305.     return EACCDN;
  306. }
  307.  
  308. static long ARGS_ON_STACK 
  309. bios_chown(fc, uid, gid)
  310.     fcookie *fc;
  311.     int uid, gid;
  312. {
  313.     UNUSED(fc); UNUSED(uid);
  314.     UNUSED(gid);
  315.     return EINVFN;
  316. }
  317.  
  318. static long ARGS_ON_STACK 
  319. bios_chmode(fc, mode)
  320.     fcookie *fc;
  321.     unsigned mode;
  322. {
  323.     UNUSED(fc); UNUSED(mode);
  324.     return EINVFN;
  325. }
  326.  
  327. long ARGS_ON_STACK 
  328. nomkdir(dir, name, mode)
  329.     fcookie *dir;
  330.     const char *name;
  331.     unsigned mode;
  332. {
  333.     UNUSED(dir); UNUSED(name);
  334.     UNUSED(mode);
  335.     return EACCDN;
  336. }
  337.  
  338. static long ARGS_ON_STACK 
  339. bios_rmdir(dir, name)
  340.     fcookie *dir;
  341.     const char *name;
  342. {
  343.     return bios_remove(dir, name);
  344. }
  345.  
  346. /*
  347.  * MAJOR BUG: we don't check here for removal of devices for which there
  348.  * are still open files
  349.  */
  350.  
  351. static long ARGS_ON_STACK 
  352. bios_remove(dir, name)
  353.     fcookie *dir;
  354.     const char *name;
  355. {
  356.     struct bios_file *b, **lastb;
  357.  
  358.     UNUSED(dir);
  359.     lastb = &broot;
  360.     for (b = broot; b; b = *(lastb = &b->next)) {
  361.         if (!stricmp(b->name, name)) break;
  362.     }
  363.     if (!b) return EFILNF;
  364.  
  365. /* don't allow removal of the basic system devices */
  366.     if (b >= BDEV && b <= bdevlast) {
  367.         return EACCDN;
  368.     }
  369.     *lastb = b->next;
  370.  
  371.     if (b->device == 0 || b->device == &bios_tdevice)
  372.         kfree(b->tty);
  373.  
  374.     kfree(b);
  375.     return 0;
  376. }
  377.  
  378. static long ARGS_ON_STACK 
  379. bios_getname(root, dir, pathname, size)
  380.     fcookie *root, *dir; char *pathname;
  381.     int size;
  382. {
  383.     char *foo = ((struct bios_file *)dir->index)->name;
  384.  
  385.     UNUSED(root);
  386.     if (dir->index == 0 && size > 0)
  387.         *pathname = 0;
  388.     else if (strlen(foo) < size)
  389.         strcpy(pathname, foo);
  390.     else
  391.         return ERANGE;
  392.     return 0;
  393. }
  394.  
  395. static long ARGS_ON_STACK 
  396. bios_rename(olddir, oldname, newdir, newname)
  397.     fcookie *olddir;
  398.     char *oldname;
  399.     fcookie *newdir;
  400.     const char *newname;
  401. {
  402.     struct bios_file *b;
  403.  
  404.     UNUSED(olddir); UNUSED(newdir);
  405.  
  406. /* BUG: we should check to see if "newname" already exists */
  407.  
  408.     for (b = broot; b; b = b->next) {
  409.         if (!stricmp(b->name, oldname)) {
  410.             strncpy(b->name, newname, BNAME_MAX);
  411.             return 0;
  412.         }
  413.     }
  414.     return EFILNF;
  415. }
  416.  
  417. static long ARGS_ON_STACK 
  418. bios_opendir(dirh, flags)
  419.     DIR *dirh;
  420.     int flags;
  421. {
  422.     UNUSED(flags);
  423.  
  424.     if (dirh->fc.index != 0) {
  425.         DEBUG(("bios_opendir: bad directory"));
  426.         return EPTHNF;
  427.     }
  428.     return 0;
  429. }
  430.  
  431. static long ARGS_ON_STACK 
  432. bios_readdir(dirh, name, namelen, fc)
  433.     DIR *dirh;
  434.     char *name;
  435.     int namelen;
  436.     fcookie *fc;
  437. {
  438.     struct bios_file *b;
  439.     int giveindex = dirh->flags == 0;
  440.     int i;
  441.  
  442.     b = broot;
  443.     i = dirh->index++;
  444.     while(i-- > 0) {
  445.         if (!b) break;
  446.         b = b->next;
  447.     }
  448.     if (!b) {
  449.         return ENMFIL;
  450.     }
  451.     fc->fs = &bios_filesys;
  452.     fc->index = (long)b;
  453.     fc->aux = b->private;
  454.     fc->dev = dirh->fc.dev;
  455.     if (giveindex) {
  456.         namelen -= (int)sizeof(long);
  457.         if (namelen <= 0)
  458.             return ERANGE;
  459.         *((long *)name) = (long) b;
  460.         name += sizeof(long);
  461.     }
  462.     strncpy(name, b->name, namelen-1);
  463.     if (strlen(b->name) >= namelen)
  464.         return ENAMETOOLONG;
  465.     return 0;
  466. }
  467.  
  468. static long ARGS_ON_STACK 
  469. bios_rewinddir(dirh)
  470.     DIR *dirh;
  471. {
  472.     dirh->index = 0;
  473.     return 0;
  474. }
  475.  
  476. static long ARGS_ON_STACK 
  477. bios_closedir(dirh)
  478.     DIR *dirh;
  479. {
  480.     UNUSED(dirh);
  481.     return 0;
  482. }
  483.  
  484. static long ARGS_ON_STACK 
  485. bios_pathconf(dir, which)
  486.     fcookie *dir;
  487.     int which;
  488. {
  489.     UNUSED(dir);
  490.  
  491.     switch(which) {
  492.     case -1:
  493.         return DP_MAXREQ;
  494.     case DP_IOPEN:
  495.         return UNLIMITED;    /* no limit on BIOS file descriptors */
  496.     case DP_MAXLINKS:
  497.         return 1;        /* no hard links available */
  498.     case DP_PATHMAX:
  499.         return PATH_MAX;
  500.     case DP_NAMEMAX:
  501.         return BNAME_MAX;
  502.     case DP_ATOMIC:
  503.         return 1;        /* no atomic writes */
  504.     case DP_TRUNC:
  505.         return DP_AUTOTRUNC;    /* names are truncated */
  506.     case DP_CASE:
  507.         return DP_CASEINSENS;    /* not case sensitive */
  508.     default:
  509.         return EINVFN;
  510.     }
  511. }
  512.  
  513. static long ARGS_ON_STACK 
  514. bios_dfree(dir, buf)
  515.     fcookie *dir;
  516.     long *buf;
  517. {
  518.     UNUSED(dir);
  519.  
  520.     buf[0] = 0;    /* number of free clusters */
  521.     buf[1] = 0;    /* total number of clusters */
  522.     buf[2] = 1;    /* sector size (bytes) */
  523.     buf[3] = 1;    /* cluster size (sectors) */
  524.     return 0;
  525. }
  526.  
  527. /*
  528.  * BIOS Dcntl() calls:
  529.  * Dcntl(0xde02, "U:\DEV\FOO", &foo_descr): install a new device called
  530.  *     "FOO", which is described by the dev_descr structure "foo_descr".
  531.  *     this structure has the following fields:
  532.  *         DEVDRV *driver        the device driver itself
  533.  *       short  dinfo            info for the device driver
  534.  *       short  flags            flags for the file (e.g. O_TTY)
  535.  *       struct tty *tty        tty structure, if appropriate
  536.  *
  537.  * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with
  538.  *     BIOS device number "n".
  539.  * Dcntl(0xde01, "U:\DEV\BAR", n): install a new non-tty BIOS device, with
  540.  *     BIOS device number "n".
  541.  */
  542.  
  543. static long ARGS_ON_STACK 
  544. bios_fscntl(dir, name, cmd, arg)
  545.     fcookie *dir;
  546.     const char *name;
  547.     int cmd;
  548.     long arg;
  549. {
  550.     struct bios_file *b;
  551.  
  552.     UNUSED(dir);
  553.     if ((unsigned)cmd == DEV_INSTALL) {
  554.         struct dev_descr *d = (struct dev_descr *)arg;
  555.  
  556.         b = kmalloc(SIZEOF(struct bios_file));
  557.         if (!b) return 0;
  558.         strncpy(b->name, name, BNAME_MAX);
  559.         b->name[BNAME_MAX] = 0;
  560.         b->device = d->driver;
  561.         b->private = d->dinfo;
  562.         b->flags = d->flags;
  563.         b->tty = d->tty;
  564.         b->next = broot;
  565.         broot = b;
  566.         return (long)&kernelinfo;
  567.     }
  568.     if ((unsigned)cmd == DEV_NEWTTY) {
  569.         b = kmalloc(SIZEOF(struct bios_file));
  570.         if (!b) return ENSMEM;
  571.         b->tty = kmalloc(SIZEOF(struct tty));
  572.         if (!b->tty) {
  573.             kfree(b);
  574.             return ENSMEM;
  575.         }
  576.         strncpy(b->name, name, BNAME_MAX);
  577.         b->name[BNAME_MAX] = 0;
  578.         b->device = &bios_tdevice;
  579.         b->private = arg;
  580.         b->flags = O_TTY;
  581.         *b->tty = default_tty;
  582.         b->next = broot;
  583.         broot = b;
  584.         return 0;
  585.     }
  586.     if ((unsigned)cmd == DEV_NEWBIOS) {
  587.         b = kmalloc(SIZEOF(struct bios_file));
  588.         if (!b) return ENSMEM;
  589.         strncpy(b->name, name, BNAME_MAX);
  590.         b->name[BNAME_MAX] = 0;
  591.         b->tty = 0;
  592.         b->device = &bios_ndevice;
  593.         b->private = arg;
  594.         b->flags = 0;
  595.         b->next = broot;
  596.         return 0;
  597.     }
  598.     return EINVFN;
  599. }
  600.  
  601. static long ARGS_ON_STACK 
  602. bios_symlink(dir, name, to)
  603.     fcookie *dir;
  604.     const char *name, *to;
  605. {
  606.     struct bios_file *b;
  607.     long r;
  608.     fcookie fc;
  609.  
  610.     r = bios_lookup(dir, name, &fc);
  611.     if (r == 0) return EACCDN;    /* file already exists */
  612.     if (r != EFILNF) return r;    /* some other error */
  613.  
  614.     b = kmalloc(SIZEOF(struct bios_file));
  615.     if (!b) return EACCDN;
  616.  
  617.     strncpy(b->name, name, BNAME_MAX);
  618.     b->name[BNAME_MAX] = 0;
  619.     b->device = 0;
  620.     b->private = EINVFN;
  621.     b->flags = 0;
  622.     b->tty = kmalloc((long)strlen(to)+1);
  623.     if (!b->tty) {
  624.         kfree(b);
  625.         return EACCDN;
  626.     }
  627.     strcpy((char *)b->tty, to);
  628.     b->next = broot;
  629.     broot = b;
  630.     return 0;
  631. }
  632.  
  633. static long ARGS_ON_STACK 
  634. bios_readlink(fc, buf, buflen)
  635.     fcookie *fc;
  636.     char *buf;
  637.     int buflen;
  638. {
  639.     struct bios_file *b = (struct bios_file *)fc->index;
  640.  
  641.     if (!b) return EINVFN;
  642.     if (b->device) return EINVFN;
  643.  
  644.     strncpy(buf, (char *)b->tty, buflen);
  645.     if (strlen((char *)b->tty) >= buflen)
  646.         return ENAMETOOLONG;
  647.     return 0;
  648. }
  649.  
  650.  
  651. /*
  652.  * routines for file systems that don't support volume labels
  653.  */
  654.  
  655. long ARGS_ON_STACK 
  656. nowritelabel(dir, name)
  657.     fcookie *dir;
  658.     const char *name;
  659. {
  660.     UNUSED(dir);
  661.     UNUSED(name);
  662.     return EACCDN;
  663. }
  664.  
  665. long ARGS_ON_STACK 
  666. noreadlabel(dir, name, namelen)
  667.     fcookie *dir;
  668.     char *name;
  669.     int namelen;
  670. {
  671.     UNUSED(dir);
  672.     UNUSED(name);
  673.     UNUSED(namelen);
  674.     return EFILNF;
  675. }
  676.  
  677. /*
  678.  * routines for file systems that don't support links
  679.  */
  680.  
  681. long ARGS_ON_STACK 
  682. nosymlink(dir, name, to)
  683.     fcookie *dir;
  684.     const char *name, *to;
  685. {
  686.     UNUSED(dir); UNUSED(name);
  687.     UNUSED(to);
  688.     return EINVFN;
  689. }
  690.  
  691. long ARGS_ON_STACK 
  692. noreadlink(dir, buf, buflen)
  693.     fcookie *dir;
  694.     char *buf;
  695.     int buflen;
  696. {
  697.     UNUSED(dir); UNUSED(buf);
  698.     UNUSED(buflen);
  699.     return EINVFN;
  700. }
  701.  
  702. long ARGS_ON_STACK 
  703. nohardlink(fromdir, fromname, todir, toname)
  704.     fcookie *fromdir, *todir;
  705.     const char *fromname, *toname;
  706. {
  707.     UNUSED(fromdir); UNUSED(todir);
  708.     UNUSED(fromname); UNUSED(toname);
  709.     return EINVFN;
  710. }
  711.  
  712. /* dummy routine for file systems with no Fscntl commands */
  713.  
  714. long ARGS_ON_STACK 
  715. nofscntl(dir, name, cmd, arg)
  716.     fcookie *dir;
  717.     const char *name;
  718.     int cmd;
  719.     long arg;
  720. {
  721.     UNUSED(dir); UNUSED(name);
  722.     UNUSED(cmd); UNUSED(arg);
  723.     return EINVFN;
  724. }
  725.  
  726. /*
  727.  * Did the disk change? Not on this drive!
  728.  * However, we have to do Getbpb anyways, because someone has decided
  729.  * to force a media change on our (non-existent) drive.
  730.  */
  731. long ARGS_ON_STACK 
  732. nodskchng(drv)
  733.     int drv;
  734. {
  735.     (void)getbpb(drv);
  736.     return 0;
  737. }
  738.  
  739. long ARGS_ON_STACK 
  740. nocreat(dir, name, mode, attrib, fc)
  741.     fcookie *dir, *fc;
  742.     const char *name;
  743.     unsigned mode;
  744.     int attrib;
  745. {
  746.     UNUSED(dir); UNUSED(fc);
  747.     UNUSED(name); UNUSED(mode);
  748.     UNUSED(attrib);
  749.     return EACCDN;
  750. }
  751.  
  752. static DEVDRV * ARGS_ON_STACK 
  753. bios_getdev(fc, devsp)
  754.     fcookie *fc;
  755.     long *devsp;
  756. {
  757.     struct bios_file *b;
  758.  
  759.     b = (struct bios_file *)fc->index;
  760.  
  761.     if (b->device && b->device != &fakedev)
  762.         *devsp = (long)b->tty;
  763.     else
  764.         *devsp = b->private;
  765.  
  766.     return b->device;    /* return the device driver */
  767. }
  768.  
  769. /*
  770.  * NULL device driver
  771.  */
  772.  
  773. long ARGS_ON_STACK 
  774. null_open(f)
  775.     FILEPTR *f;
  776. {
  777.     UNUSED(f);
  778.     return 0;
  779. }
  780.  
  781. long ARGS_ON_STACK 
  782. null_write(f, buf, bytes)
  783.     FILEPTR *f; const char *buf; long bytes;
  784. {
  785.     UNUSED(f); UNUSED(buf);
  786.     return bytes;
  787. }
  788.  
  789. long ARGS_ON_STACK 
  790. null_read(f, buf, bytes)
  791.     FILEPTR *f; char *buf; long bytes;
  792. {
  793.     UNUSED(f); UNUSED(buf);
  794.     UNUSED(bytes);
  795.     return 0;
  796. }
  797.  
  798. long ARGS_ON_STACK 
  799. null_lseek(f, where, whence)
  800.     FILEPTR *f; long where; int whence;
  801. {
  802.     UNUSED(f); UNUSED(whence);
  803.     return (where == 0) ? 0 : ERANGE;
  804. }
  805.  
  806. long ARGS_ON_STACK 
  807. null_ioctl(f, mode, buf)
  808.     FILEPTR *f; int mode; void *buf;
  809. {
  810.     UNUSED(f);
  811.     if (mode == FIONREAD) {
  812.         *((long *)buf) = 0;
  813.     }
  814.     else if (mode == FIONWRITE)
  815.         *((long *)buf) = 1;
  816.     else
  817.         return EINVFN;
  818.     return 0;
  819. }
  820.  
  821. long ARGS_ON_STACK 
  822. null_datime(f, timeptr, rwflag)
  823.     FILEPTR *f;
  824.     short *timeptr;
  825.     int rwflag;
  826. {
  827.     UNUSED(f);
  828.     if (rwflag)
  829.         return EACCDN;
  830.     *timeptr++ = timestamp;
  831.     *timeptr = datestamp;
  832.     return 0;
  833. }
  834.  
  835. long ARGS_ON_STACK 
  836. null_close(f, pid)
  837.     FILEPTR *f;
  838.     int pid;
  839. {
  840.     UNUSED(f);
  841.     UNUSED(pid);
  842.     return 0;
  843. }
  844.  
  845. long ARGS_ON_STACK 
  846. null_select(f, p, mode)
  847.     FILEPTR *f; long p;
  848.     int mode;
  849. {
  850.     UNUSED(f); UNUSED(p);
  851.     UNUSED(mode);
  852.     return 1;    /* we're always ready to read/write */
  853. }
  854.  
  855. void ARGS_ON_STACK 
  856. null_unselect(f, p, mode)
  857.     FILEPTR *f;
  858.     long p;
  859.     int mode;
  860. {
  861.     UNUSED(f); UNUSED(p);
  862.     UNUSED(mode);
  863.     /* nothing to do */
  864. }
  865.  
  866. /*
  867.  * BIOS terminal device driver
  868.  */
  869.  
  870. static long ARGS_ON_STACK 
  871. bios_topen(f)
  872.     FILEPTR *f;
  873. {
  874.     f->flags |= O_TTY;
  875.     return 0;
  876. }
  877.  
  878. /*
  879.  * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag
  880.  * set), bios_read and bios_write will only ever be called indirectly, via
  881.  * tty_read and tty_write. That's why we can afford to play a bit fast and
  882.  * loose with the pointers ("buf" is really going to point to a long) and
  883.  * why we know that "bytes" is divisible by 4.
  884.  */
  885.  
  886. static long ARGS_ON_STACK 
  887. bios_twrite(f, buf, bytes)
  888.     FILEPTR *f; const char *buf; long bytes;
  889. {
  890.     long *r;
  891.     long ret = 0;
  892.     int bdev = f->fc.aux;
  893.  
  894.     r = (long *)buf;
  895.  
  896. /* Check for control characters on any newline output.
  897.  * Note that newlines are always output through tty_putchar,
  898.  * so they'll always be the first thing in the buffer (at least,
  899.  * for cooked TTY output they will, which is the only sort that
  900.  * control characters affect anyways).
  901.  */
  902.     if (bytes > 0 && (*r & 0x000000ffL) == '\n')
  903.         (void) checkkeys();
  904.  
  905.     if (f->flags & O_NDELAY) {
  906.         while (bytes > 0) {
  907.             if (!bcostat(bdev)) break;
  908.             if (bconout(bdev, (int)*r) == 0)
  909.             break;
  910.             r++; bytes -= 4; ret+= 4;
  911.         }
  912.     } else {
  913.         while (bytes > 0) {
  914.             if (bconout(bdev, (int)*r) == 0)
  915.             break;
  916.             r++; bytes -= 4; ret+= 4;
  917.         }
  918.     }
  919. #if 0
  920.     (void)checkkeys();
  921. #endif
  922.     return ret;
  923. }
  924.  
  925. static long ARGS_ON_STACK 
  926. bios_tread(f, buf, bytes)
  927.     FILEPTR *f; char *buf; long bytes;
  928. {
  929.     long *r, ret = 0;
  930.     int bdev = f->fc.aux;
  931.  
  932.     r = (long *)buf;
  933.  
  934.     if ((f->flags & O_NDELAY)) {
  935.         while (bytes > 0) {
  936.             if ( !bconstat(bdev) )
  937.             break;
  938.             *r++ = bconin(bdev) & 0x7fffffffL;
  939.             bytes -= 4; ret += 4;
  940.         }
  941.     } else {
  942.         while (bytes > 0) {
  943.             *r++ = bconin(bdev) & 0x7fffffffL;
  944.             bytes -= 4; ret += 4;
  945.         }
  946.     }
  947.     return ret;
  948. }
  949.  
  950. /*
  951.  * read/write routines for BIOS devices that aren't terminals (like the
  952.  * printer & IKBD devices)
  953.  */
  954.  
  955. static long ARGS_ON_STACK 
  956. bios_nwrite(f, buf, bytes)
  957.     FILEPTR *f; const char *buf; long bytes;
  958. {
  959.     long ret = 0;
  960.     int bdev = f->fc.aux;
  961.     int c;
  962.  
  963.     while (bytes > 0) {
  964.         if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
  965.             break;
  966.  
  967.         c = *buf++ & 0x00ff;
  968.  
  969.         if (bconout(bdev, c) == 0)
  970.             break;
  971.  
  972.         bytes--; ret++;
  973.     }
  974.     return ret;
  975. }
  976.  
  977. static long ARGS_ON_STACK 
  978. bios_nread(f, buf, bytes)
  979.     FILEPTR *f; char *buf; long bytes;
  980. {
  981.     long ret = 0;
  982.     int bdev = f->fc.aux;
  983.  
  984.     while (bytes > 0) {
  985.         if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
  986.             break;
  987.         *buf++ = bconin(bdev) & 0xff;
  988.         bytes--; ret++;
  989.     }
  990.     return ret;
  991. }
  992.  
  993. /*
  994.  * BIOS terminal seek code -- this has to match the documented
  995.  * way to do isatty()
  996.  */
  997.  
  998. static long ARGS_ON_STACK 
  999. bios_tseek(f, where, whence)
  1000.     FILEPTR *f;
  1001.     long where;
  1002.     int whence;
  1003. {
  1004.     UNUSED(f); UNUSED(where);
  1005.     UNUSED(whence);
  1006. /* terminals always are at position 0 */
  1007.     return 0;
  1008. }
  1009.  
  1010. #define MAXBAUD 16
  1011.  
  1012. /* keep these sorted in descending order */
  1013. static long baudmap[MAXBAUD] = {
  1014. 19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  1015. 600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  1016. };
  1017.  
  1018. static long ARGS_ON_STACK 
  1019. bios_ioctl(f, mode, buf)
  1020.     FILEPTR *f; int mode; void *buf;
  1021. {
  1022.     long *r = (long *)buf;
  1023.     struct winsize *ws;
  1024.     char *aline;
  1025.     short dev;
  1026.     int i;
  1027.  
  1028.     if (mode == FIONREAD) {
  1029.         if (bconstat(f->fc.aux))
  1030.             *r = 1;
  1031.         else
  1032.             *r = 0;
  1033.     }
  1034.     else if (mode == FIONWRITE) {
  1035.         if (bcostat(f->fc.aux))
  1036.             *r = 1;
  1037.         else
  1038.             *r = 0;
  1039.     }
  1040.     else if (mode == TIOCFLUSH) {
  1041. /* BUG: this should flush the input/output buffers */
  1042.         return 0;
  1043.     }
  1044.     else if (mode == TIOCGWINSZ && f->fc.aux == 2) {
  1045.         aline = lineA0();
  1046.         ws = (struct winsize *)buf;
  1047.         ws->ws_row = *((short *)(aline - 42)) + 1;
  1048.         ws->ws_col = *((short *)(aline - 44)) + 1;
  1049.     } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) {
  1050.         long oldbaud, newbaud;
  1051.         int oldmap;
  1052.  
  1053.         dev = f->fc.aux;
  1054.  
  1055.         newbaud = *r;
  1056.         if (dev == 1 || dev >= 6) {
  1057. /* trick rsconf into setting the correct port (it uses curproc->bconmap) */
  1058.             oldmap = curproc->bconmap;
  1059.             if (has_bconmap)
  1060.                 curproc->bconmap = 
  1061.                     (dev == 1) ? curproc->bconmap : dev;
  1062.             i = (int)rsconf(-2, -1, -1, -1, -1, -1);
  1063.  
  1064.             if (i < 0 || i >= MAXBAUD)
  1065.                 oldbaud = -1L;
  1066.             else
  1067.                 oldbaud = baudmap[i];
  1068.             *r = oldbaud;
  1069.             if (newbaud > 0 && newbaud != oldbaud) {
  1070.     /* BUG: assert DTR works only on modem1 */
  1071.                 if (dev == 1 || dev == 6) {
  1072.                     Offgibit(0xef);
  1073.                 }
  1074.                 for (i = 0; i < MAXBAUD; i++) {
  1075.                     if (baudmap[i] == newbaud) {
  1076.                         rsconf(i, -1, -1, -1, -1, -1);
  1077.                         curproc->bconmap = oldmap;
  1078.                         return 0;
  1079.                     } else if (baudmap[i] < newbaud) {
  1080.                         *r = baudmap[i];
  1081.                         curproc->bconmap = oldmap;
  1082.                         break;
  1083.                     }
  1084.                 }
  1085.                 curproc->bconmap = oldmap;
  1086.                 return ERANGE;
  1087.             } else if (newbaud == 0L) {
  1088.     /* BUG: drop DTR: works only on modem1 */
  1089.                 if (dev == 1 || dev == 6) {
  1090.                     Ongibit(0x10);
  1091.                 }
  1092.             }
  1093.             curproc->bconmap = oldmap;
  1094.             return 0;
  1095.         } else if (dev == 2 || dev == 5) {
  1096.             /* screen: assume 9600 baud */
  1097.             oldbaud = 9600L;
  1098.         } else if (dev == 3) {
  1099.             /* midi */
  1100.             oldbaud = 31250L;
  1101.         } else {
  1102.             oldbaud = -1L;    /* unknown speed */
  1103.         }
  1104.         *r = oldbaud;
  1105.         if (newbaud > 0 && newbaud != oldbaud)
  1106.             return ERANGE;
  1107.         return 0;
  1108.     } else if (mode == TIOCCBRK || mode == TIOCSBRK) {
  1109.         unsigned long bits;
  1110.  
  1111.         dev = f->fc.aux;
  1112.         if (dev == 1 || dev >= 6) {
  1113.             if (has_bconmap)
  1114.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1115.         } else {
  1116.             return EINVFN;
  1117.         }
  1118.         bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1119.         bits = (bits >> 8) & 0x0ff;        /* isolate TSR byte */
  1120.         if (mode == TIOCCBRK)
  1121.             bits &= ~8;
  1122.         else
  1123.             bits |= 8;
  1124.         (void)rsconf(-1, -1, -1, -1, (int)bits, -1);
  1125.     } else if (mode == TIOCGFLAGS || mode == TIOCSFLAGS) {
  1126.         unsigned short oflags, flags;
  1127.         unsigned long bits;
  1128.         unsigned char ucr;
  1129.         short flow;
  1130.  
  1131.         dev = f->fc.aux;
  1132.         if (dev == 1 || dev >= 6) {
  1133.             oflags = ((struct tty *)f->devinfo)->sg.sg_flags;
  1134.             oflags &= (T_TANDEM|T_RTSCTS);
  1135.             if (has_bconmap)
  1136.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1137.             bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1138.             ucr = (bits >> 24L) & 0x0ff;        /* isolate UCR byte */
  1139.             oflags |= (ucr >> 3) & (TF_STOPBITS|TF_CHARBITS);
  1140.             if (ucr & 0x4) {            /* parity on? */
  1141.                 oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
  1142.             }
  1143.             if (mode == TIOCSFLAGS) {
  1144.                 flags = (*(unsigned short *)buf);
  1145.                 if (flags & T_EVENP) {
  1146.                     ucr |= 0x6;
  1147.                 } else if (flags & T_ODDP) {
  1148.                     ucr &= ~2;
  1149.                     ucr |= 0x4;
  1150.                 } else {
  1151.                     ucr &= ~6;
  1152.                 }
  1153.                 if (flags & TF_STOPBITS) {
  1154.                     ucr &= ~(0x18);
  1155.                     ucr |= (flags & TF_STOPBITS) << 3;
  1156.                 }
  1157.                 ucr &= ~(0x60);
  1158.                 ucr |= (flags & TF_CHARBITS) << 3;
  1159.                 flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L;
  1160.                 rsconf(-1, flow, ucr, -1, -1, -1);
  1161.             } else {
  1162.                 *((unsigned short *)buf) = oflags;
  1163.             }
  1164.         } else {
  1165.             return EINVFN;
  1166.         }
  1167.     } else if ((mode >= TCURSOFF && mode <= TCURSSTEADY) && (f->fc.aux == 2)) {
  1168.         return Cursconf(mode - TCURSOFF, 0);
  1169.     } else if ((mode >= TCURSSRATE && mode <= TCURSGRATE) && (f->fc.aux == 2)) {
  1170.         long r;
  1171.  
  1172.         r = Cursconf(mode - TCURSOFF, *((short *)buf));
  1173.         if (r >= 0) {
  1174.             *(short *)buf = r;
  1175.             r = 0;
  1176.         }
  1177.         return r;
  1178.     } else {
  1179.     /* Fcntl will automatically call tty_ioctl to handle
  1180.      * terminal calls that we didn't deal with
  1181.      */
  1182.         return EINVFN;
  1183.     }
  1184.     return 0;
  1185. }
  1186.  
  1187. static long ARGS_ON_STACK 
  1188. bios_select(f, p, mode)
  1189.     FILEPTR *f; long p; int mode;
  1190. {
  1191.     struct tty *tty = (struct tty *)f->devinfo;
  1192.     int dev = f->fc.aux;
  1193.  
  1194.     if (mode == O_RDONLY) {
  1195.         if (bconstat(dev)) {
  1196.             TRACE(("bios_select: data present for device %d", dev));
  1197.             return 1;
  1198.         }
  1199.         if (tty) {
  1200.         /* avoid collisions with other processes */
  1201.             if (!tty->rsel)
  1202.                 tty->rsel = p;
  1203.         }
  1204.         return 0;
  1205.     } else if (mode == O_WRONLY) {
  1206.         if (bcostat(dev)) {
  1207.             TRACE(("bios_select: ready to output on %d", dev));
  1208.             return 1;
  1209.         }
  1210.         if (tty) {
  1211.             if (!tty->wsel)
  1212.                 tty->wsel = p;
  1213.         }
  1214.         return 0;
  1215.     }
  1216.     /* default -- we don't know this mode, return 0 */
  1217.     return 0;
  1218. }
  1219.  
  1220. static void ARGS_ON_STACK 
  1221. bios_unselect(f, p, mode)
  1222.     FILEPTR *f;
  1223.     long p;
  1224.     int mode;
  1225. {
  1226.     struct tty *tty = (struct tty *)f->devinfo;
  1227.  
  1228.     if (tty) {
  1229.         if (mode == O_RDONLY && tty->rsel == p)
  1230.             tty->rsel = 0;
  1231.         else if (mode == O_WRONLY && tty->wsel == p)
  1232.             tty->wsel = 0;
  1233.     }
  1234. }
  1235.  
  1236. /*
  1237.  * mouse device driver
  1238.  */
  1239.  
  1240. #define MOUSESIZ 128*3
  1241. static unsigned char mousebuf[MOUSESIZ];
  1242. static int mousehead, mousetail;
  1243.  
  1244. long mousersel;    /* is someone calling select() on the mouse? */
  1245.  
  1246. char mshift;        /* shift key status; set by checkkeys() in bios.c */
  1247. short *gcurx = 0,
  1248.       *gcury = 0;    /* mouse pos. variables; used by big screen emulators */
  1249.  
  1250. void ARGS_ON_STACK 
  1251. mouse_handler(buf)
  1252.     const char *buf;    /* must be a *signed* character */
  1253. {
  1254.     unsigned char *mbuf, buttons;
  1255.     int newmtail;
  1256.     short dx, dy;
  1257.  
  1258. /* the Sun mouse driver has 0=down, 1=up, while the atari hardware gives
  1259.    us the reverse. also, we have the "middle" button and the "left"
  1260.    button reversed; so we use this table to convert (and also to add the
  1261.    0x80 to indicate a mouse packet)
  1262.  */
  1263.     static int _cnvrt[8] = {
  1264.         0x87, 0x86, 0x83, 0x82, 0x85, 0x84, 0x81, 0x80
  1265.     };
  1266.  
  1267.     mbuf = &mousebuf[mousetail];
  1268.     newmtail = mousetail + 3;
  1269.     if (newmtail >= MOUSESIZ)
  1270.         newmtail = 0;
  1271.     if (newmtail == mousehead)
  1272.         return;            /* buffer full */
  1273.  
  1274.     buttons = *buf++ & 0x7;        /* convert to SUN format */
  1275.     if (mshift & 0x3) {        /* a shift key held down? */
  1276.     /* if so, convert shift+button to a "middle" button */
  1277.         if (buttons == 0x1 || buttons == 0x2)
  1278.             buttons = 0x4;
  1279.         else if (buttons == 0x3)
  1280.             buttons = 0x7;
  1281.     }
  1282.     *mbuf++ = _cnvrt[buttons];    /* convert to Sun format */
  1283.     dx = *buf++;
  1284.     *mbuf++ = dx;            /* copy X delta */
  1285.     dy = *buf;
  1286.     *mbuf = -dy;            /* invert Y delta for Sun format */
  1287.     mousetail = newmtail;
  1288.     *gcurx += dx;            /* update line A variables */
  1289.     *gcury += dy;
  1290. /*
  1291.  * if someone has called select() waiting for mouse input, wake them
  1292.  * up
  1293.  */
  1294.     if (mousersel) {
  1295.         wakeselect(mousersel);
  1296.     }
  1297. }
  1298.  
  1299. extern void newmvec(), newjvec();    /* in intr.s */
  1300. static long oldvec = 0;
  1301. long oldjvec = 0;
  1302.  
  1303. static long ARGS_ON_STACK 
  1304. mouse_open(f)
  1305.     FILEPTR *f;
  1306. {
  1307.     char *aline;
  1308.  
  1309.     static char parameters[] = {
  1310.         0,         /* Y=0 in lower corner */
  1311.         0,        /* normal button handling */
  1312.         1, 1        /* X, Y scaling factors */
  1313.     };
  1314.  
  1315.     UNUSED(f);
  1316.  
  1317.     if (oldvec)        /* mouse in use */
  1318.         return EACCDN;
  1319.  
  1320. /* initialize pointers to line A variables */
  1321.     if (!gcurx) {
  1322.         aline = lineA0();
  1323.         if (aline == 0)    {    /* should never happen */
  1324.             ALERT("unable to read line A variables");
  1325.             return -1;
  1326.         }
  1327.         gcurx = (short *)(aline - 0x25a);
  1328.         gcury = (short *)(aline - 0x258);
  1329.         *gcurx = *gcury = 32;    /* magic number -- what MGR uses */
  1330.     }
  1331.  
  1332.     oldvec = syskey->mousevec;
  1333.     oldjvec = syskey->joyvec;    /* jr: save old joystick vector */
  1334.     Initmous(1, parameters, newmvec);
  1335.     syskey->joyvec = (long)newjvec;    /* jr: set up new joystick handler */
  1336.     mousehead = mousetail = 0;
  1337.     return 0;
  1338. }
  1339.  
  1340. static long ARGS_ON_STACK 
  1341. mouse_close(f, pid)
  1342.     FILEPTR *f;
  1343.     int pid;
  1344. {
  1345.     static char parameters[] = {
  1346.         0,         /* Y=0 in lower corner */
  1347.         0,        /* normal button handling */
  1348.         1, 1        /* X, Y scaling factors */
  1349.     };
  1350.  
  1351.     UNUSED(pid);
  1352.     if (!f) return EIHNDL;
  1353.     if (f->links <= 0) {
  1354.         if (!oldvec) {
  1355.             DEBUG(("Mouse not open!!"));
  1356.             return -1;
  1357.         }
  1358.         Initmous(1, parameters, (void *)oldvec);    /* gratuitous (void *) for Lattice */
  1359.         syskey->joyvec = oldjvec;    /* jr: restore old joystick handler */
  1360.         oldvec = 0;
  1361.     }
  1362.     return 0;
  1363. }
  1364.  
  1365. static long ARGS_ON_STACK 
  1366. mouse_read(f, buf, nbytes)
  1367.     FILEPTR *f;
  1368.     char *buf;
  1369.     long nbytes;
  1370. {
  1371.     long count = 0;
  1372.     int mhead;
  1373.     unsigned char *foo;
  1374.  
  1375.     mhead = mousehead;
  1376.     foo = &mousebuf[mhead];
  1377.  
  1378.     if (mhead == mousetail) {
  1379.         if (f->flags & O_NDELAY)
  1380.             return 0;
  1381.         do {
  1382.             yield();
  1383.         } while (mhead == mousetail);
  1384.     }
  1385.  
  1386.     while ( (mhead != mousetail) && (nbytes > 0)) {
  1387.         *buf++ = *foo++;
  1388.         mhead++;
  1389.         if (mhead >= MOUSESIZ) {
  1390.             mhead = 0;
  1391.             foo = mousebuf;
  1392.         }
  1393.         count++;
  1394.         --nbytes;
  1395.     }
  1396.     mousehead = mhead;
  1397.     return count;
  1398. }
  1399.  
  1400. static long ARGS_ON_STACK 
  1401. mouse_ioctl(f, mode, buf)
  1402.     FILEPTR *f;
  1403.     int mode;
  1404.     void *buf;
  1405. {
  1406.     long r;
  1407.  
  1408.     UNUSED(f);
  1409.     if (mode == FIONREAD) {
  1410.         r = mousetail - mousehead;
  1411.         if (r < 0) r += MOUSESIZ;
  1412.         *((long *)buf) = r;
  1413.     }
  1414.     else
  1415.         return EINVFN;
  1416.     return 0;
  1417. }
  1418.  
  1419. static long ARGS_ON_STACK 
  1420. mouse_select(f, p, mode)
  1421.     FILEPTR *f;
  1422.     long p;
  1423.     int mode;
  1424. {
  1425.     UNUSED(f);
  1426.  
  1427.     if (mode != O_RDONLY)
  1428.         return 1;    /* we can always take output :-) */
  1429.  
  1430.     if (mousetail - mousehead)
  1431.         return 1;    /* input waiting already */
  1432.  
  1433.     if (!mousersel)
  1434.         mousersel = p;
  1435.     return 0;
  1436. }
  1437.  
  1438. static void ARGS_ON_STACK 
  1439. mouse_unselect(f, p, mode)
  1440.     FILEPTR *f;
  1441.     long p;
  1442.     int mode;
  1443. {
  1444.     UNUSED(f);
  1445.  
  1446.     if (mode == O_RDONLY && mousersel == p)
  1447.         mousersel = 0;
  1448. }
  1449.  
  1450.  
  1451. /*
  1452.  * UTILITY ROUTINE called by Bconmap() in xbios.c:
  1453.  * this sets handle -1 of process p to a file handle
  1454.  * that has BIOS device "dev". Returns 0 on failure,
  1455.  * non-zero on success.
  1456.  */
  1457.  
  1458. int
  1459. set_auxhandle(p, dev)
  1460.     PROC *p;
  1461.     int dev;
  1462. {
  1463.     FILEPTR *f;
  1464.     struct bios_file *b;
  1465.  
  1466.     f = new_fileptr();
  1467.     if (f) {
  1468.         f->links = 1;
  1469.         f->flags = O_RDWR;
  1470.         f->pos = 0;
  1471.         f->devinfo = 0;
  1472.         f->fc.fs = &bios_filesys;
  1473.         f->fc.aux = dev;
  1474.         f->fc.dev = BIOSDRV;
  1475.         for (b = broot; b; b = b->next) {
  1476.             if (b->private == dev &&
  1477.                 (b->device == &bios_tdevice ||
  1478.                  b->device == &bios_ndevice)) {
  1479.                 f->fc.index = (long)b;
  1480.                 f->dev = b->device;
  1481.                 if (b->device != &fakedev)
  1482.                     f->devinfo = (long)b->tty;
  1483.                 goto found_device;
  1484.             }
  1485.         }
  1486.         f->fc.index = 0;
  1487.         f->dev = &bios_ndevice;
  1488. found_device:
  1489.         if ((*f->dev->open)(f) < 0) {
  1490.             f->links = 0;
  1491.             dispose_fileptr(f);
  1492.             return 0;
  1493.         }
  1494.     } else {
  1495. /* no memory! use the fake FILEPTR we
  1496.  * set up in biosfs_init
  1497.  */
  1498.         f = defaultaux;
  1499.         f->links++;
  1500.     }
  1501.  
  1502.     (void)do_pclose(p, p->aux);
  1503.     p->aux = f;
  1504.  
  1505.     return 1;
  1506. }
  1507.